﻿using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using FutureCode.Game.Command;
using System;

/// <summary>
/// 士兵行为类
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class SoldierBehaviour : MonoBehaviour, IMoveableObject {

    /// <summary>
    /// 士兵生命值
    /// </summary>
    public int Life = 100;
    /// <summary>
    /// 士兵奔跑速度
    /// </summary>
    public float RunSpeed = 5;
    /// <summary>
    /// 士兵是否存活
    /// </summary>
    public bool  IsLive { get { return Life > 0; } }
    //public GameObject BulletPrefab;
    /// <summary>
    /// 士兵的角色控制器
    /// </summary>
    public CharacterController controller;
    /// <summary>
    /// IMoveableObject接口实现属性，方便ShadowBehaviour调用
    /// </summary>
    public GameObject Object { get { return gameObject; } }
    /// <summary>
    /// IMoveableObject接口实现属性，方便ShadowBehaviour调用
    /// </summary>
    public Vector3 Position
    {
        get
        {
            return transform.position;
        }
        set
        {
            transform.position = value;
        }
    }
    /// <summary>
    /// IMoveableObject接口实现属性，方便ShadowBehaviour调用
    /// </summary>
    public Quaternion Rotation
    {
        get
        {
            return transform.rotation;
        }
        set
        {
            transform.rotation = value;
        }
    }

    SoldierAnimationBehaviour anim;
    GameObject bulletPrefab;
    GameSettings settings;
    ShadowBehaviour shadowBehaviour;

    /// <summary>
    /// 是否正在进行射击
    /// </summary>
    public bool Shotting = false;

    bool running = false;
    //float cameraHeight;
    //float cameraDistance;
    // Use this for initialization
    void Start () {
        settings = GameSettings.Instance;
        bulletPrefab = transform.FindChild("Bullet").gameObject;
        var animator = GetComponent<Animator>();
        anim = animator.GetBehaviour<SoldierAnimationBehaviour>();
        anim.soldier_behaviour = this;
        controller = GetComponent<CharacterController>();

        shotLayerMask = ~((1 << LayerMask.NameToLayer("UnShot")) | 1 << LayerMask.NameToLayer("BirthPoint"));

        if (NetManager.Instance.Connected && !settings.IsPlayerClient)
        {
            //如果是非玩家客户端，则给士兵创建影子
            GameObject obj = GameObject.Instantiate(ShadowManager.Instance.ShadowPrefab,
                Vector3.zero, Quaternion.identity) as GameObject;
            obj.name = "Shadow_Player";
            shadowBehaviour = obj.GetComponent<ShadowBehaviour>();
            shadowBehaviour.OriginObject = this;
            shadowBehaviour.TriggerSize = new Vector3(0.1f, 0.1f, 0.1f);

            shadowBehaviour.AddEventListener(BehaviourType.Attack, Shot);
        }
    }
    Vector3 previousTargetDirection;
	// Update is called once per frame
	void Update () {
        if(settings.IsPlayerClient && Life > 0)
        {
            //如果士兵存活且当前客户端为玩家客户端，则使用键盘/鼠标进行士兵控制
            if (!Shotting && Input.GetMouseButtonDown(0))
            {
                Shotting = true;
                previousTargetDirection = Vector3.zero;

                ShotAim();

                var cmd = GetCurrentStateCmd(PlayerChangedStateType.Shot);
                NetManager.Instance.Send(cmd);

                Shot();
            }

            if(!Shotting)
            {
                Vector3 targetDirection = new Vector3();
                targetDirection.x = InputManager.instance.Horizontal;
                targetDirection.z = InputManager.instance.Vertical;
                if (targetDirection.x > 0)
                    targetDirection.x = 1;
                else if (targetDirection.x < 0)
                    targetDirection.x = -1;
                if (targetDirection.z > 0)
                    targetDirection.z = 1;
                else if (targetDirection.z < 0)
                    targetDirection.z = -1;

                if (targetDirection == Vector3.zero)
                {
                    if(running)
                        StopMove();
                }
                else
                {
                    if (targetDirection != previousTargetDirection)
                    {
                        transform.forward = targetDirection.normalized;
                        Move();
                    }
                }

                previousTargetDirection = targetDirection;
            }
        }
    }

    /// <summary>
    /// IMoveableObject实现方法，用于士兵移动（玩家客户端）/影子跟随（非玩家客户端）
    /// </summary>
    public void Move()
    {
        anim.start_run = true;
        anim.end_run = false;
        running = true;
        if(settings.IsPlayerClient)
        {
            PlayerStateChangedCommand cmd = GetCurrentStateCmd(PlayerChangedStateType.StartMove);
            NetManager.Instance.Send(cmd);
        }
    }
    /// <summary>
    /// IMoveableObject实现方法，用于士兵停止移动（玩家客户端）/停止影子跟随（非玩家客户端）
    /// </summary>
    public void StopMove()
    {
        anim.start_run = false;
        anim.end_run = true;
        running = false;
        if (settings.IsPlayerClient)
        {
            PlayerStateChangedCommand cmd = GetCurrentStateCmd(PlayerChangedStateType.EndMove);
            NetManager.Instance.Send(cmd);
        }
    }

    /// <summary>
    /// 同步-奔跑
    /// </summary>
    /// <param name="position">开始奔跑位置</param>
    /// <param name="rotation">开始奔跑旋转</param>
    /// <param name="time">开始奔跑时间</param>
    public void RunSync(Vector3 position, Quaternion rotation, DateTime time)
    {
        if(settings.EnableSyncStrategy)
        {
            shadowBehaviour.Move(position, rotation, RunSpeed, time, NetManager.Instance.Clock.Now);
        }
        else
        {
            transform.position = position;
            transform.rotation = rotation;
            Move();
        }
    }
    /// <summary>
    /// 同步-停止奔跑
    /// </summary>
    /// <param name="position">停止奔跑位置</param>
    /// <param name="rotation">停止奔跑旋转</param>
    /// <param name="time">停止奔跑时间</param>
    public void StopRunSync(Vector3 position, Quaternion rotation, DateTime time)
    {
        if(settings.EnableSyncStrategy)
        {
            shadowBehaviour.StopMove(position, rotation);
        }
        else
        {
            transform.position = position;
            transform.rotation = rotation;
            StopMove();
        }
    }

    /// <summary>
    /// 获取当前状态指令
    /// </summary>
    /// <param name="type">要获取的指令类型</param>
    /// <returns>状态指令</returns>
    public PlayerStateChangedCommand GetCurrentStateCmd(PlayerChangedStateType type)
    {
        PlayerStateChangedCommand cmd = new PlayerStateChangedCommand();
        cmd.PosX = transform.position.x;
        cmd.PosY = transform.position.y;
        cmd.PosZ = transform.position.z;
        cmd.RotationW = transform.rotation.w;
        cmd.RotationX = transform.rotation.x;
        cmd.RotationY = transform.rotation.y;
        cmd.RotationZ = transform.rotation.z;
        cmd.Time = NetManager.Instance.Clock.Now;
        cmd.ChangedStateType = type;
        return cmd;
    }
    /// <summary>
    /// 通知非玩家客户端玩家状态改变
    /// </summary>
    /// <param name="cmd">状态指令</param>
    public void PlayerStateChanged(PlayerStateChangedCommand cmd)
    {
        Vector3 position = new Vector3(cmd.PosX, cmd.PosY, cmd.PosZ);
        Quaternion rotation = new Quaternion(cmd.RotationX, cmd.RotationY,
            cmd.RotationZ, cmd.RotationW);

        PlayerChangedStateType type = cmd.ChangedStateType;
        DateTime cmdTime = cmd.Time;
        switch(type)
        {
            case PlayerChangedStateType.StartMove:
                RunSync(position, rotation, cmdTime);
                break;
            case PlayerChangedStateType.EndMove:
                StopRunSync(position, rotation, cmdTime);
                break;
            case PlayerChangedStateType.Shot:
                ShotAsync(position, rotation, cmdTime);
                break;
            case PlayerChangedStateType.Injured:
                this.Life -= 10;
                break;
            case PlayerChangedStateType.Dead:
                transform.rotation = rotation;
                Life = 0;
                anim.death = true;
                shadowBehaviour.enabled = false;
                break;
            case PlayerChangedStateType.Reborn:
                Life = 100;
                anim.reset = true;
                transform.position = position;
                transform.rotation = rotation;
                shadowBehaviour.enabled = true;
                break;
        }
    }

    int shotLayerMask;
    /// <summary>
    /// 玩家客户端进行射击瞄准
    /// </summary>
    void ShotAim()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 100, shotLayerMask, QueryTriggerInteraction.Ignore))
        {
            var pos = hit.point;
            var direction = pos - transform.position;
            transform.forward = Vector3.ProjectOnPlane(direction, Vector3.up).normalized;
        }
    }
    /// <summary>
    /// 射击
    /// </summary>
    void Shot()
    {
        anim.shot = true;

        var bullet = (GameObject)GameObject.Instantiate(bulletPrefab, bulletPrefab.transform.position, bulletPrefab.transform.rotation);
        bullet.GetComponent<CapsuleCollider>().enabled = true;
        bullet.GetComponent<MeshRenderer>().enabled = true;
        Rigidbody rb = bullet.GetComponent<Rigidbody>();
        rb.velocity =  transform.forward * 10;
    }
    
    /// <summary>
    /// 射击同步
    /// </summary>
    /// <param name="position">射击位置</param>
    /// <param name="rotation">射击旋转</param>
    /// <param name="time">射击时间</param>
    void ShotAsync(Vector3 position, Quaternion rotation, DateTime time)
    {
        if (settings.EnableSyncStrategy)
        {
            shadowBehaviour.AddBehaviour(position, rotation, BehaviourType.Attack);
        }
        else
        {
            Shotting = true;
            previousTargetDirection = Vector3.zero;
            transform.position = position;
            transform.rotation = rotation;
            Shot();
        }
    }

    /// <summary>
    /// 触发器进入，用于受怪兽攻击判断
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other)
    {
        if (!settings.IsPlayerClient) return;

        if (Life <= 0)
            return;
        string triggerName = other.transform.name;
        if (triggerName != "Sword") return;

        Life -= 10;

        if (Life <= 0)
        {
            Death(other.transform);
        }
        else if (GameSettings.Instance.IsPlayerClient)
        {
            var cmd = GetCurrentStateCmd(PlayerChangedStateType.Injured);
            NetManager.Instance.Send(cmd);
        }
    }
    /// <summary>
    /// 控制玩家死亡
    /// </summary>
    /// <param name="attacker"></param>
    void Death(Transform attacker)
    {
        anim.death = true;
        attacker = attacker.parent;

        var direction = attacker.position - transform.position;
        direction = Vector3.ProjectOnPlane(direction, Vector3.up);
        Quaternion lookRotation = Quaternion.LookRotation(direction);
        transform.rotation = lookRotation;

        if (GameSettings.Instance.IsPlayerClient)
        {
            var cmd = GetCurrentStateCmd(PlayerChangedStateType.Dead);
            NetManager.Instance.Send(cmd);
        }

        //士兵死亡后开始重生
        StartCoroutine(Reborn());
    }

    /// <summary>
    /// 士兵重生
    /// </summary>
    /// <returns></returns>
    IEnumerator Reborn()
    {
        //等待3秒
        yield return new WaitForSeconds(3);
        while (BirthPoint.UnUsedPoint.Count == 0)
            yield return new WaitForSeconds(1);
        var pos = BirthPoint.GetEmptyPoint();
        anim.reset = true;
        transform.position = pos.Value;
        Life = 100;
        transform.LookAt(new Vector3(30, 0, 30));

        var cmd = GetCurrentStateCmd(PlayerChangedStateType.Reborn);
        NetManager.Instance.Send(cmd);
    }
}
